import os, sys
from Sanae3D.lib.ModelObject import Model3D
from Sanae3D.lib.StructReader import StructReader

class WarOfDragons_XAC(Model3D):
    '''Replace 'WarOfDragons_XAC' with a suitable name of your choice. Try to follow
    the standard: GameName_FormatExt'''
    
    def __init__(self, obj3D=None, outFile=None, inFile=None):
        
        super(WarOfDragons_XAC,self).__init__("XAC")
        self.obj3D = obj3D
        self.inFile = inFile
        self.outFile = outFile
        
    def parse_faces(self, meshName, numFaces, matNum):
        
        for i in xrange(numFaces):
            v1, v2, v3 = self.inFile.read_long(3)
            
            self.create_face(meshName, i)
            self.add_face_verts(meshName, i, [v1, v2, v3])
            self.add_face_material(meshName, i, matNum)
            
    def parse_vertices(self, meshName, numVerts):
        
        for i in xrange(numVerts):
            vx, vy, vz = self.inFile.read_float(3)
            self.create_vertex(meshName, i)
            self.add_coords(meshName, i, [vx, vy, vz])
    
    def parse_normals(self, meshName, numVerts):
        
        for i in xrange(numVerts):
            nx, ny, nz = self.inFile.read_float(3)
            
            self.add_vert_normals(meshName, i, [nx, ny, nz])
            
    def parse_weights(self, meshName, numVerts):
        
        for i in xrange(numVerts):
            w1, w2, w3, w4 = self.inFile.read_float(4)
            
            self.add_vert_weights(meshName, i, [w1, w2, w3, w4])
            
    def parse_uv(self, meshName, numVerts):
        
        for i in xrange(numVerts):
            tu, tv = self.inFile.read_float(2)
            self.add_vert_uv(meshName, i, [tu, tv])
            
    def parse_materials(self, offsets):
        
        for i in xrange(len(offsets)):
            
            print i
        
    def parse_textures(self, offsets):
        
        for i in xrange(len(offsets)):
            self.inFile.seek(offsets[i])
            self.inFile.read_float(7)
            charCount = self.inFile.read_long()
            texName = self.inFile.read_string(charCount)
            self.create_material(i)
            self.add_material_name(i, texName)
            self.add_texture_name(i, texName)
            print i, texName

    def parse_face_section(self, name, numSects, vertStart, normStart,
                    weightStart, uvStart, faceStart, vertIDStart):
        
        for i in xrange(numSects):
            meshName = "%s[%d]" %(name, i)
            self.create_object(meshName)
            
            self.inFile.seek(faceStart[i])
            numFaces = self.inFile.read_long() / 3
            numVerts, matID, usedBoneID = self.inFile.read_long(3)
            #print numFaces, numVerts
            print matID
            self.parse_faces(meshName, numFaces, matID - 1)
            
            for j in xrange(usedBoneID):
                boneID = self.inFile.read_long()
            
            faceStart.append(self.inFile.tell())
            if len(vertIDStart) != 0:
                self.inFile.seek(vertIDStart[i])
                for j in xrange(numVerts):
                    vertID = self.inFile.read_long()
                vertIDStart.append(self.inFile.tell())
                
            if len(vertStart) != 0:
                self.inFile.seek(vertStart[i])
                self.parse_vertices(meshName, numVerts)
                vertStart.append(self.inFile.tell())
                
            if len(normStart) > 0:
                self.inFile.seek(normStart[i])
                self.parse_normals(meshName, numVerts)
                normStart.append(self.inFile.tell())
                
            if len(weightStart) > 0:
                self.inFile.seek(weightStart[i])
                self.parse_weights(meshName, numVerts)
                weightStart.append(self.inFile.tell())
                
            if len(uvStart) > 0:
                self.inFile.seek(uvStart[i])
                self.parse_uv(meshName, numVerts)
                uvStart.append(self.inFile.tell())
                
    def parse_meshes(self, offsets):
        
        for i in xrange(len(offsets)):
            meshName = "obj[%d]" %i
            offset = offsets[i]
            self.inFile.seek(offset)
            count1, count2, count3, count4 = self.inFile.read_long(4)
            numFaceSects = self.inFile.read_long()
            count5, count6, count7, count8, count9 = self.inFile.read_long(5)
            
            vertStart = []
            normStart = []
            weightStart = []
            uvStart = []
            faceStart = []
            vertIDStart = []
            vertIDStart.append(self.inFile.tell())
            
            for i in xrange(count3):
                self.inFile.seek(4, 1)
                
            for i in xrange(count5 - 1):
                type1, size, unk1 = self.inFile.read_long(3)
                curPos = self.inFile.tell()
                if type1 == 0:
                    vertStart.append(curPos)
                    for j in xrange(count3):
                        self.inFile.seek(0xC, 1)
                elif type1 == 1:
                    normStart.append(curPos)
                    for j in xrange(count3):
                        self.inFile.seek(0xC, 1)
                elif type1 == 2:
                    weightStart.append(curPos)
                    for j in xrange(count3):
                        self.inFile.seek(0x10, 1)
                elif type1 == 3:
                    uvStart.append(curPos)
                    for j in xrange(count3):
                        self.inFile.seek(0x8, 1)
            
            faceStart.append(self.inFile.tell())
            self.parse_face_section(meshName, numFaceSects, vertStart, normStart,
                                weightStart, uvStart, faceStart, vertIDStart)
        
    def parse_file(self):
        '''Main parser method. Can be replaced'''
        
        filesize = self.inFile.filesize()
        idstring = self.inFile.read_string(4)
        
        id1, id2, id3, id4 = self.inFile.read_ubyte(4)
        
        typesOfs = [[], [], [], [], [], [], [], [], []]
        meshNames = []
        
        while self.inFile.tell() != filesize:
            type1, size, type2 = self.inFile.read_long(3)
            curPos = self.inFile.tell()
            
            if type1 == 0:
                typesOfs[0].append(curPos)
            if type1 == 1:
                typesOfs[1].append(curPos)
            elif type1 == 2:
                typesOfs[2].append(curPos)
            elif type1 == 3:
                if type2 == 2:
                    typesOfs[3].append(curPos)
                elif type2 == 10000:
                    typesOfs[3].append(curPos)
            elif type1 == 4:
                typesOfs[4].append(curPos)
            elif type1 == 5:
                typesOfs[5].append(curPos)
            elif type1 == 6:
                typesOfs[6].append(curPos)
            elif type1 == 7:
                typesOfs[7].append(curPos)
            self.inFile.seek(size, 1)
            
        #bones
        
        #weights
        
        #materials
        self.parse_materials(typesOfs[3])
        
        #textures
        self.parse_textures(typesOfs[4])
        
        #mesh
        self.parse_meshes(typesOfs[1])
                                     
                                     
        
def read_file(path):
    '''Read the file'''
    
    openFile = StructReader(open(path, 'rb'))
    obj = WarOfDragons_XAC(inFile=openFile)
    obj.parse_file()
    openFile.close()
    return obj

def write_file(path):
    
    pass

def definitions():
    '''Return the header, extension, and a description of the format'''
    
    return "XAC", "XAC", "War of Dragons XAC"

if __name__ == '__main__':
    
    file1 = "mb_bo_bownomal_01-up.xac"
    file2 = "pc_sh_iron02_01-up.xac"
    obj = read_file(file1)